<?php
namespace App\Services;

use App\Model\MaterialAssign;
use App\Model\MaterialFlow;
use App\Model\MaterialReportScore;
use App\Model\MaterialSheetAssign;
use App\Repositories\MaterialAssignRepository;
use App\Repositories\MaterialFlowRepository;
use App\Repositories\MaterialProjectSheetRepository;
use App\Repositories\MaterialReportRepository;
use App\Repositories\MaterialRepository;
use App\Repositories\MaterialSheetAssignRepository;
use App\Traits\ReturnTrait;
use Hyperf\DbConnection\Db;
use App\Services\AdminService;
use Hyperf\Di\Annotation\Inject;

class MaterialService
{
    use ReturnTrait;

    /**
     * @Inject
     * @var AdminService
     */
    public $admin_service;
    /**
     * @param $params
     * @param $admin
     * @return array
     */

    public function report($params,$admin){
        $material_id = $params['material_id'];
        $material_assign_id = $params['material_assign_id'];
        $report_data = $params['submit_data'];
        $material = MaterialRepository::getInstance()->getById($material_id);
        if(!$material){
            return $this->error('材料清单不存在');
        }
        if(strtotime($material->start_time)>time()){
            return $this->error('材料上报还未开始');
        }
        if(strtotime($material->end_time)<time()){
            return $this->error('材料上报已结束');
        }
        DB::beginTransaction();
        try{
            $old_report_ids = MaterialReportRepository::getInstance()->all('id',[[
                'field' => 'material_id',
                'value' => $material_id
            ],[
                'field' => 'material_assign_id',
                'value' => $material_assign_id,
            ],[
                'field' => 'admin_id',
                'value' => $admin->id
            ]]);
            $old_report_ids = collect($old_report_ids)->pluck('id')->toArray();
            $now_update_ids=[];
            foreach ($report_data as $key=>$item){
                foreach ($item['files'] as $k=>$file){
                    $insert_data=[
                        'admin_id' => $admin->id,
                        'material_id' => $item['material_id'],
                        'material_assign_id' => $item['material_assign_id'],
                        'material_project_id' => $item['material_project_id'],
                        'path' => $file['path'],
                        'file_type' => $file['type'],
                        'file_name' => $file['name'],
                        'file_size' => $file['size']
                    ];
                    if($file['id']>0){
                        $insert_data['id'] = $file['id'];
                     }
                    $report_result = MaterialReportRepository::getInstance()->store($insert_data);
                    if(!$report_result['success']){
                        throw new \Exception($report_result['msg']);
                    }
                    $now_update_ids[]=$report_result['data']->id;
                }
            }
            $delete_ids = array_merge(array_diff($old_report_ids,$now_update_ids));
            if(!empty($delete_ids)){
                MaterialReportRepository::getInstance()->deleteAll([[
                    'field' => 'id',
                    'value' => $delete_ids,
                    'method' => 'in'
                ]]);
            }
            //更新状态
            $assign_result = MaterialAssignRepository::getInstance()->store([
                'id' => $material_assign_id,
                'status' => MaterialAssign::STATUS_ISUPLOAD
            ]);
            if(!$assign_result['success']){
                throw new \Exception('状态更新失败');
            }
            //分配审核流程
//            $return_flow=$this->createFlow($material_id,$material_assign_id,$admin);
//            if(!$return_flow['success']){
//                throw new \Exception($return_flow['msg']);
//            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }

    public function reportSheet($params,$admin){
        $material_id = $params['material_id'];
        $material_assign_id = $params['material_assign_id'];
        $material_project_id = $params['material_project_id'];
        $material_sheet_id = $params['material_sheet_id'];
        $report_data = $params['submit_data'];

        $material = MaterialRepository::getInstance()->getById($material_id);
        $assign = MaterialSheetAssignRepository::getInstance()->getById($material_assign_id);
        $sheet = MaterialProjectSheetRepository::getInstance()->getById($material_sheet_id);
        if(!$assign){
            return $this->error('材料未分配');
        }
        if(!$material){
            return $this->error('材料清单不存在');
        }
        if(!$sheet){
            return $this->error('材料清单项目内容不存在');
        }
        if(strtotime($material->start_time)>time()){
            return $this->error('材料上报还未开始');
        }
        if(strtotime($material->end_time)<time()){
            return $this->error('材料上报已结束');
        }
        $max_score = $sheet->report_num*$sheet->single_score;
        DB::beginTransaction();
        try{
            $old_report_ids = MaterialReportRepository::getInstance()->all('id',[[
                'field' => 'material_assign_id',
                'value' => $material_assign_id,
            ]]);
            $old_report_ids = collect($old_report_ids)->pluck('id')->toArray();
            $now_update_ids=[];
            foreach ($report_data as $key=>$item){
                $insert_data=[
                    'admin_id' => $admin->id,
                    'material_id' => $material_id,
                    'material_assign_id' => $material_assign_id,
                    'material_project_id' => $material_project_id,
                    'material_sheet_id' => $material_sheet_id,
                    'path' => $item['path'],
                    'file_type' => $item['type'],
                    'file_name' => $item['name'],
                    'file_size' => $item['size']
                ];
                if($item['id']>0){
                    $insert_data['id'] = $item['id'];
                }
                $report_result = MaterialReportRepository::getInstance()->store($insert_data);
                if(!$report_result['success']){
                    throw new \Exception($report_result['msg']);
                }
                $now_update_ids[]=$report_result['data']->id;
            }
            $delete_ids = array_merge(array_diff($old_report_ids,$now_update_ids));
            if(!empty($delete_ids)){
                MaterialReportRepository::getInstance()->deleteAll([[
                    'field' => 'id',
                    'value' => $delete_ids,
                    'method' => 'in'
                ]]);
            }
            //更新状态和分数
            $upload_score = count($report_data)*$sheet->single_score;
            $upload_score = $upload_score>$max_score?$max_score:$upload_score;
            $assign_result = MaterialSheetAssignRepository::getInstance()->store([
                'id' => $material_assign_id,
                'status' => MaterialSheetAssign::STATUS_ISUPLOAD,
                'all_score' => $upload_score
            ]);
            if(!$assign_result['success']){
                throw new \Exception('状态更新失败');
            }
            //分配审核流程
//            $return_flow=$this->createFlow($material_id,$material_assign_id,$admin);
//            if(!$return_flow['success']){
//                throw new \Exception($return_flow['msg']);
//            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }

    public function submitVerify($material_assign_id,$admin){
        $material_assign = MaterialAssignRepository::getInstance()->getById($material_assign_id);
        DB::beginTransaction();
        try{
            $assign_result = MaterialAssignRepository::getInstance()->store([
                'id' => $material_assign_id,
                'status' => MaterialAssign::STATUS_WAITVERIRY
            ]);
            if(!$assign_result['success']){
                throw new \Exception('状态更新失败');
            }

            $return_flow=$this->createFlow($material_assign->material_id,$material_assign_id,$admin);
            if(!$return_flow['success']){
                throw new \Exception($return_flow['msg']);
            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }

    public function submitVerifySheet($material_assign_id,$admin){
        $material_assign = MaterialSheetAssignRepository::getInstance()->getById($material_assign_id);
        DB::beginTransaction();
        try{
            $assign_result = MaterialSheetAssignRepository::getInstance()->store([
                'id' => $material_assign_id,
                'status' => MaterialSheetAssign::STATUS_WAITVERIRY
            ]);
            if(!$assign_result['success']){
                throw new \Exception('状态更新失败');
            }
            //清除被打回流程，重新开始流程
            $count = MaterialFlow::query()->where('material_assign_id',$material_assign_id)
                ->where('status',MaterialFlow::STATUS_VERIFYFAIl)
                ->where('is_end',1)
                ->where('flow_type',MaterialFlow::FLOW_TYPE_ONE)
                ->count('id');
            if($count){
                if(
                !MaterialFlow::query()->where('material_assign_id',$material_assign_id)
                    ->where('status',MaterialFlow::STATUS_VERIFYFAIl)
                    ->where('is_end',1)
                    ->where('flow_type',MaterialFlow::FLOW_TYPE_ONE)->delete()
                ){
                    throw new \Exception('流程删除失败');
                }
            }
            $return_flow=$this->createFlow($material_assign->material_id,$material_assign_id,$admin);
            if(!$return_flow['success']){
                throw new \Exception($return_flow['msg']);
            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }

    public function verify($params,$admin){
        $flow_id = $params['flow_id'];
        $status = $params['status'];
        $mask = $params['mask'];
        $flow = MaterialFlowRepository::getInstance()->getById($flow_id);
        DB::beginTransaction();
        try{
            $flow->mask = $mask;
            $flow->status = $status;
            $flow->is_end = 1;
            if(!$flow->save()){
                throw new \Exception('状态更新失败');
            }
            $assign = MaterialAssignRepository::getInstance()->getById($flow->material_assign_id);
            if($status==MaterialFlow::STATUS_VERIFYSUCCESS){
                $return_flow=$this->createFlow($flow->material_id,$flow->material_assign_id,$admin);
                if(!$return_flow['success']){
                    throw new \Exception($return_flow['msg']);
                }
                $next_flow = $return_flow['data']['flow'];
                if($next_flow->flow_type==MaterialFlow::FLOW_TYPE_ONE){
                    if($assign->status==MaterialAssign::STATUS_WAITVERIRY){
                        $assign->status = MaterialAssign::STATUS_VERIFY;
                        if(!$assign->save()){
                            throw new \Exception('状态2更新失败');
                        }
                    }
                }else{
                    if($assign->status!=MaterialAssign::STATUS_VERIFYSUCCESS){
                        $assign->status = MaterialAssign::STATUS_VERIFYSUCCESS;
                        if(!$assign->save()){
                            throw new \Exception('状态2更新失败');
                        }
                    }
                }
            }else{
                $assign->status = MaterialAssign::STATUS_VERIFYFAIL;
                if(!$assign->save()){
                    throw new \Exception('状态2更新失败');
                }
            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }

    public function verifySheet($params,$admin){
        $flow_id = $params['flow_id'];
        $status = $params['status'];
        $mask = $params['mask'];
        $flow = MaterialFlowRepository::getInstance()->getById($flow_id);
        DB::beginTransaction();
        try{
            $flow->mask = $mask;
            $flow->status = $status;
            $flow->is_end = 1;
            if(!$flow->save()){
                throw new \Exception('状态更新失败');
            }
            $assign = MaterialSheetAssignRepository::getInstance()->getById($flow->material_assign_id);
            if($status==MaterialFlow::STATUS_VERIFYSUCCESS){
                $return_flow=$this->createFlow($flow->material_id,$flow->material_assign_id,$admin);
                if(!$return_flow['success']){
                    throw new \Exception($return_flow['msg']);
                }
                $next_flow = $return_flow['data']['flow'];
                if($next_flow->flow_type==MaterialFlow::FLOW_TYPE_ONE){
                    if($assign->status==MaterialSheetAssign::STATUS_WAITVERIRY){
                        $assign->status = MaterialSheetAssign::STATUS_VERIFY;
                        if(!$assign->save()){
                            throw new \Exception('状态2更新失败');
                        }
                    }
                }else{
                    if($assign->status!=MaterialSheetAssign::STATUS_VERIFYSUCCESS){
                        $assign->status = MaterialSheetAssign::STATUS_VERIFYSUCCESS;
                        if(!$assign->save()){
                            throw new \Exception('状态2更新失败');
                        }
                    }
                }
            }else{
                $assign->status = MaterialSheetAssign::STATUS_VERIFYFAIL;
                if(!$assign->save()){
                    throw new \Exception('状态2更新失败');
                }
                //审核通过流程回溯
                $first_id = MaterialFlow::query()->where('material_assign_id',$flow->material_assign_id)
                    ->where('from_data_id',$assign->data_id)
                    ->where('flow_type',MaterialFlow::FLOW_TYPE_ONE)
                    ->where('id','<',$flow->id)
                    ->where('is_end',1)
                    ->select(['id'])
                    ->orderBy('id','desc')->first();
                if($first_id){
                    $count_verify =  MaterialFlow::query()->where('material_assign_id',$flow->material_assign_id)
                        ->where('status',MaterialFlow::STATUS_VERIFYSUCCESS)
                        ->where('flow_type',MaterialFlow::FLOW_TYPE_ONE)
                        ->where('id','>=',$first_id->id)
                        ->where('is_end',1)
                        ->where('id','<',$flow->id)->count('id');
                    if($count_verify){
                        MaterialFlow::query()->where('material_assign_id',$flow->material_assign_id)
                            ->where('status',MaterialFlow::STATUS_VERIFYSUCCESS)
                            ->where('flow_type',MaterialFlow::FLOW_TYPE_ONE)
                            ->where('id','>=',$first_id)
                            ->where('is_end',1)
                            ->where('id','<',$flow->id)
                            ->update([
                                'status' => MaterialFlow::STATUS_VERIFYFAIl,
                                'mask' => '上级打回'
                            ]);
                    }
                }

            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }


    public function scoreSheet($params,$admin){
        $flow_id = $params['flow_id'];
        $score = $params['score'];
        $flow = MaterialFlowRepository::getInstance()->getById($flow_id);
        $assign = MaterialSheetAssignRepository::getInstance()->getById($flow->material_assign_id);
        $sheet = MaterialProjectSheetRepository::getInstance()->one(['report_num','single_score'],[[
            'field' => 'id',
            'value' => $assign->sheet_id
        ]]);
        $limit_max = $sheet->report_num*$sheet->single_score;
        if($score>$limit_max){
            return $this->error('分数上限为'.$limit_max.'分，您打的分值已超出');
        }
        DB::beginTransaction();
        try{
            $flow->status = MaterialFlow::STATUS_SCORE;
            $flow->is_end = 1;
            if(!$flow->save()){
                throw new \Exception('状态更新失败');
            }
            //更新分值
            $assign->status = MaterialAssign::STATUS_SCORE;
            $assign->final_score = sprintf('%.1f',$score);
            if(!$assign->save()){
                throw new \Exception('分值更新失败');
            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }

    public function score($params,$admin){
        $flow_id = $params['flow_id'];
        $score = json_decode($params['score'],true);
        $flow = MaterialFlowRepository::getInstance()->getById($flow_id);
        DB::beginTransaction();
        try{
            $flow->status = MaterialFlow::STATUS_SCORE;
            $flow->is_end = 1;
            if(!$flow->save()){
                throw new \Exception('状态更新失败');
            }
            //更新项目分值
            $sum_score=0;
            foreach($score as $key=>$item){
                $sum_score+=$item['score'];
                $result = MaterialReportScore::query()->where('material_id',$flow->material_id)
                    ->where('material_assign_id',$flow->material_assign_id)
                    ->where('material_project_id',$item['id'])->first();
                if(!$result){
                    $result = new MaterialReportScore();
                    $result->material_id = $flow->material_id;
                    $result->material_assign_id = $flow->material_assign_id;
                    $result->material_project_id = $item['id'];
                }
                $result->score = $item['score'];
                if(!$result->save()){
                    throw new \Exception('项目分值更新失败');
                }
            }
            $assign = MaterialAssignRepository::getInstance()->getById($flow->material_assign_id);
            $assign->status = MaterialAssign::STATUS_SCORE;
            $assign->all_score = $sum_score;
            if(!$assign->save()){
                throw new \Exception('分值更新失败');
            }
            DB::commit();
        }catch(\Exception $e){
            DB::rollBack();
            return $this->error($e->getMessage());
        }
        return $this->success([]);
    }

    public function createFlow($material_id,$material_assign_id,$admin){
        $self = $this->admin_service->getFlowSelf($admin);
//        $is_exists = MaterialFlowRepository::getInstance()->one('id',[[
//            'field' => 'material_id',
//            'value' => $material_id
//        ],[
//            'field' => 'material_assign_id',
//            'value' => $material_assign_id
//        ],[
//            'field' => 'from_data_id',
//            'value' => $self['data_id']
//        ],[
//            'field' => 'from_data_type',
//            'value' => $self['type']
//        ]]);
//        if($is_exists){
//            return false;
//        }
        $parent = $this->admin_service->getFlowParent($admin);
        $parent_flow = MaterialFlowRepository::getInstance()->one('id',[[
            'field' => 'material_id',
            'value' => $material_id
        ],[
            'field' => 'material_assign_id',
            'value' => $material_assign_id
        ],[
            'field' => 'to_data_type',
            'value' => $parent['type']
        ],[
            'field' => 'to_data_id',
            'value' => $parent['parent_id']
        ],[
            'field' => 'is_end',
            'value' => 0
        ]]);
        if($parent_flow){
           return $this->success([
               'flow' => $parent_flow,
               'self' => $self,
               'parent' => $parent
           ]);
        }
        $sheet_assign = MaterialSheetAssignRepository::getInstance()->one(['data_id','type'],[[
            'field' => 'id',
            'value' => $material_assign_id
        ]]);
        $material_assign = MaterialAssignRepository::getInstance()->one(['id'],[[
            'field' => 'material_id',
            'value' => $material_id
        ],[
            'field' => 'data_id',
            'value' => $sheet_assign->data_id
        ],[
            'field' => 'type',
            'value' => $sheet_assign->type
        ]]);
        $insert_flow=[
            'material_id' => $material_id,
            'assign_parent_id' => $material_assign->id,
            'material_assign_id' => $material_assign_id,
            'flow_type' => $parent['type']?MaterialFlow::FLOW_TYPE_ONE:MaterialFlow::FLOW_TYPE_TWO,
            'status' => $parent['type']?MaterialFlow::STATUS_DEFAULT:MaterialFlow::STATUS_WAITSCORE,
            'from_admin_id' => $admin->id,
            'from_data_id' => $self['data_id'],
            'from_data_type' => $self['type'],
            'to_data_id' => $parent['parent_id'],
            'to_data_type' => $parent['type']
        ];
        $result_flow = MaterialFlowRepository::getInstance()->store($insert_flow);
        return $this->success([
            'flow' => $result_flow['data'],
            'self' => $self,
            'parent' => $parent
        ]);
    }

}
